package vip.xiaonuo.client.modular.wxpay.controller;

import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import vip.xiaonuo.auth.core.util.StpClientUtil;
import vip.xiaonuo.biz.modular.order.entity.BizOrder;
import vip.xiaonuo.biz.modular.order.entity.BizUserTicket;
import vip.xiaonuo.biz.modular.order.param.BizTicketOrderIdParam;
import vip.xiaonuo.biz.modular.order.service.BizTicketOrderService;
import vip.xiaonuo.biz.modular.order.service.BizUserTicketService;
import vip.xiaonuo.biz.modular.ticket.entity.Ticket;
import vip.xiaonuo.biz.modular.ticket.service.TicketService;
import vip.xiaonuo.client.modular.wxpay.service.MyWxPayService;
import vip.xiaonuo.client.modular.wxpay.util.DingTalkUtil;
import vip.xiaonuo.client.modular.wxpay.util.WxPaySignUtil;
import vip.xiaonuo.client.modular.wxuser.entity.ClientUser;
import vip.xiaonuo.common.annotation.CommonLog;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.pojo.CommonResult;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/client/c/wxpay")
@Api(tags = "微信支付")
@ApiSupport(author = "SNOWY_TEAM", order = 7)
public class WxPayController {

    @Resource
    private BizTicketOrderService bizTicketOrderService;

    @Resource
    private BizUserTicketService bizUserTicketService;
    @Resource
    private TicketService ticketService;

    @Resource
    private MyWxPayService myWxPayService;

    @Resource
    @Qualifier("wxPayV3Service")
    private WxPayService wxPayService;

    @Value("${wx.pay.notifyUrl}")
    private String notifyUrl;

    @Value("${wx.pay.apiv3-key}")
    private String apiv3Key;

    @Value("${wx.pay.private-key-path}")
    private String privateKeyPath;

    @Value("${wx.pay.private-cert-path}")
    private String privateCertPath;

    @Value("${ding_talk.webhook:}")
    private String dingTalkWebhook;

    // 私钥内容缓存
    private String privateKeyContent;

    // 日期格式化
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @PostConstruct
    public void init() {
        try {
            loadPrivateKeyContent();
        } catch (Exception e) {
            log.error("初始化微信支付私钥失败", e);
        }
    }

    /**
     * 加载私钥内容
     */
    private void loadPrivateKeyContent() {
        try {
            // 尝试从classpath加载
            if (privateKeyPath.startsWith("classpath:")) {
                String path = privateKeyPath.substring("classpath:".length());
                log.info("从classpath加载私钥: {}", path);
                cn.hutool.core.io.resource.Resource resource = new ClassPathResource(path);
                privateKeyContent = resource.readStr(StandardCharsets.UTF_8);
                log.info("成功从classpath加载私钥，长度: {}", privateKeyContent.length());
            } else {
                // 其他方式加载
                log.info("从文件系统加载私钥: {}", privateKeyPath);
                java.nio.file.Path path = java.nio.file.Paths.get(privateKeyPath);
                privateKeyContent = new String(java.nio.file.Files.readAllBytes(path), StandardCharsets.UTF_8);
                log.info("成功从文件系统加载私钥，长度: {}", privateKeyContent.length());
            }
        } catch (IOException e) {
            log.error("加载私钥内容失败: {}", privateKeyPath, e);
            throw new RuntimeException("加载私钥内容失败: " + e.getMessage(), e);
        }
    }

    /**
     * 发送订单支付成功通知到钉钉
     */
    private void sendOrderPaymentNotification(BizOrder order, Date payTime) {
        if (StrUtil.isBlank(dingTalkWebhook)) {
            log.info("钉钉webhook未配置，跳过发送通知");
            return;
        }

        try {
            // 获取订单的下单人信息
            List<BizUserTicket> userTickets = bizUserTicketService.byorder(order.getId());
            String userName = "未知";
            String userPhone = "未知";
            if (userTickets != null && !userTickets.isEmpty()) {
                userName = userTickets.get(0).getUserName();
                userPhone = userTickets.get(0).getUserPhone();
            }

            // 判断预约时间
            String reservationInfo = order.getReservationTime() != null ?
                DATE_FORMAT.format(order.getReservationTime()) : "未预约";

            // 构建消息内容
            StringBuilder content = new StringBuilder();
            content.append("【鑫享旅行订单】支付成功提醒\n\n");
            content.append("订单号: ").append(order.getId()).append("\n");
            content.append("下单人: ").append(userName).append("\n");
            content.append("手机号: ").append(userPhone).append("\n");
            content.append("景点名称: ").append(order.getSpotName() != null ? order.getSpotName() : "未知").append("\n");
            content.append("门票名称: ").append(order.getTicketName()).append("\n");
            content.append("购买数量: ").append(order.getTicketCount()).append("\n");
            content.append("订单金额: ").append(order.getPrice()).append("元\n");
            content.append("创建时间: ").append(DATE_FORMAT.format(order.getCreateTime())).append("\n");
            content.append("支付时间: ").append(payTime != null ? DATE_FORMAT.format(payTime) : "未知").append("\n");
            content.append("预约时间: ").append(reservationInfo);

            // 发送钉钉消息
            DingTalkUtil.sendMessage(dingTalkWebhook, null, content.toString(), false);
        } catch (Exception e) {
            log.error("发送钉钉通知失败", e);
        }
    }

    /**
     * 验证微信支付配置
     */
    @PostMapping("/validateConfig")
    @ApiOperation(value = "验证微信支付配置", notes = "用于检查微信支付配置是否有效")
    public CommonResult<Map<String, Object>> validateConfig() {
        Map<String, Object> result = new HashMap<>();
        try {
            // 获取配置信息
            result.put("appId", wxPayService.getConfig().getAppId());
            result.put("mchId", wxPayService.getConfig().getMchId());
            result.put("notifyUrl", notifyUrl);

            // v3 API配置信息
            result.put("apiv3Key", apiv3Key);
            result.put("privateKeyPath", privateKeyPath);
            result.put("privateCertPath", privateCertPath);

            // 检查证书是否存在
            try {
                result.put("certSerialNumber", wxPayService.getConfig().getCertSerialNo());
                result.put("certPath", wxPayService.getConfig().getKeyPath());
                result.put("hasCertificate", true);
            } catch (Exception e) {
                log.error("获取证书序列号失败", e);
                result.put("hasCertificate", false);
                result.put("certError", e.getMessage());
            }

            // 检查API V3 Key是否设置
            result.put("hasApiV3Key", StrUtil.isNotBlank(wxPayService.getConfig().getApiV3Key()));

            // 检查私钥内容
            result.put("privateKeyLoaded", StrUtil.isNotBlank(privateKeyContent));
            if (StrUtil.isNotBlank(privateKeyContent)) {
                result.put("privateKeyLength", privateKeyContent.length());
                result.put("privateKeyPreview", privateKeyContent.substring(0, Math.min(50, privateKeyContent.length())) + "...");
            }

            result.put("configValid", true);
            return CommonResult.data(result);
        } catch (Exception e) {
            log.error("验证微信支付配置失败", e);
            result.put("configValid", false);
            result.put("error", e.getMessage());
            return CommonResult.data(result);
        }
    }

    /**
     * 创建微信支付订单
     */
    @ApiOperationSupport(order = 1)
    @ApiOperation("创建支付订单")
    @PostMapping("/createOrder")
    @CommonLog("创建微信支付订单")
    public CommonResult<Map<String, Object>> createOrder(@RequestBody BizTicketOrderIdParam bizTicketOrderIdParam, HttpServletRequest request) {
        try {
            // 1.查询订单信息
            BizOrder order = bizTicketOrderService.detail(bizTicketOrderIdParam);
            if (order == null) {
                throw new CommonException("订单不存在！");
            }

            if (!"待支付".equals(order.getStatus())) {
                throw new CommonException("订单状态不是待支付！");
            }

            if (order.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
                throw new CommonException("订单金额为0或负数，无需支付！");
            }

            // 2.获取当前登录用户
            ClientUser user = JSONUtil.toBean(StpClientUtil.getSession().get("wxuser").toString(), ClientUser.class);
            log.info("创建支付订单 - 用户信息: userId={}, openId={}", user.getId(), user.getOpenId());

            if (StrUtil.isBlank(user.getOpenId())) {
                throw new CommonException("用户未绑定微信OpenID，无法发起支付");
            }

            // 3.调用微信支付API V3创建支付订单
            WxPayUnifiedOrderV3Request orderRequest = new WxPayUnifiedOrderV3Request();
            orderRequest.setOutTradeNo(order.getId());
            orderRequest.setDescription("门票购买-" + order.getTicketName());

            // 设置支付者信息
            WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
            payer.setOpenid(user.getOpenId());
            orderRequest.setPayer(payer);

            // 设置商品信息
            WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
            // 总金额，单位为分
            int totalFee = order.getPrice().multiply(new BigDecimal("100")).intValue();
            amount.setTotal(totalFee);
            amount.setCurrency("CNY");
            orderRequest.setAmount(amount);

            // 设置通知地址
            orderRequest.setNotifyUrl(notifyUrl + "/notifyV3");

            // 判断订单是否存在邀请用户ID，如果有则标记为分账订单
            // 2025-07-02   修改所有有分账金额的票的订单都为分账订单
            Ticket ticket = ticketService.getById(order.getTicketId());
            if ((StrUtil.isNotBlank(order.getInvitationUserId()) && !"undefined".equals(order.getInvitationUserId()))
                || (ticket.getCommissionOneDlr() != null && ticket.getCommissionOneDlr().compareTo(BigDecimal.ZERO) > 0)
                || (ticket.getCommissionTwoDlr() != null && ticket.getCommissionTwoDlr().compareTo(BigDecimal.ZERO) > 0)
            ) {
                log.info("订单{}存在邀请用户ID: {}，标记为分账订单", order.getId(), order.getInvitationUserId());
                // 将分账字段设置为true
                WxPayUnifiedOrderV3Request.SettleInfo settleInfo = new WxPayUnifiedOrderV3Request.SettleInfo();
                settleInfo.setProfitSharing(true);
                orderRequest.setSettleInfo(settleInfo);
            }

            // 调用接口获取支付参数
            log.info("发起微信支付V3下单请求，订单号:{}, 交易类型:{}, 金额:{}", order.getId(), TradeTypeEnum.JSAPI, totalFee);
            WxPayUnifiedOrderV3Result wxPayUnifiedOrderV3Result = wxPayService.unifiedOrderV3(TradeTypeEnum.JSAPI, orderRequest);
            log.info("获取微信支付V3下单成功，订单号:{}, prepayId:{}", order.getId(), wxPayUnifiedOrderV3Result.getPrepayId());

            // 获取JSAPI调起支付的参数
            log.info("开始生成微信支付参数，appId: {}, prepayId: {}",
                wxPayService.getConfig().getAppId(),
                wxPayUnifiedOrderV3Result.getPrepayId());

            // 确保私钥内容已加载
            if (StrUtil.isBlank(privateKeyContent)) {
                loadPrivateKeyContent();
            }

            Map<String, String> payInfo = WxPaySignUtil.createPaySignatureWithPrivateKey(
                wxPayService.getConfig().getAppId(),
                wxPayUnifiedOrderV3Result.getPrepayId(),
                privateKeyContent
            );
            log.info("生成JSAPI支付参数成功，订单号:{}, 参数:{}", order.getId(), payInfo);

            // 更新订单的wxOrderId字段，存储预支付ID
            bizTicketOrderService.lambdaUpdate()
                    .eq(BizOrder::getId, order.getId())
                    .set(BizOrder::getWxOrderId, wxPayUnifiedOrderV3Result.getPrepayId())
                    .update();

            log.info("已更新订单wxOrderId字段，存储预支付ID，订单ID: {}, prepayId: {}", order.getId(), wxPayUnifiedOrderV3Result.getPrepayId());

            // 构建返回结果
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("orderId", order.getId());
            resultMap.put("payInfo", payInfo);
            resultMap.put("prepayId", wxPayUnifiedOrderV3Result.getPrepayId());

            return CommonResult.data(resultMap);
        } catch (WxPayException e) {
            log.error("创建微信支付订单失败 - 微信支付异常: returnCode={}, returnMsg={}, resultCode={}, errCode={}, errCodeDes={}",
                      e.getReturnCode(), e.getReturnMsg(), e.getResultCode(), e.getErrCode(), e.getErrCodeDes());

            log.error("微信支付请求完整日志", e);
            throw new CommonException("创建微信支付订单失败: " + e.getReturnMsg());
        } catch (Exception e) {
            log.error("创建微信支付订单失败", e);
            throw new CommonException("创建微信支付订单失败: " + e.getMessage());
        }
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StrUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        // 如果是多级代理，取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }

        // 如果获取不到，则默认使用本地IP
        if (StrUtil.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        return ip;
    }

    /**
     * 支付结果通知处理V3
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation("支付结果通知V3")
    @PostMapping("/notifyV3")
    public String handlePayNotifyV3(@RequestBody String notifyData, HttpServletRequest request) {
        log.info("接收到微信支付V3结果通知：{}", notifyData);

        // V3通知需要验证签名，从请求头获取
        String wechatpaySignature = request.getHeader("Wechatpay-Signature");
        String wechatpayTimestamp = request.getHeader("Wechatpay-Timestamp");
        String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
        String wechatpaySerial = request.getHeader("Wechatpay-Serial");

        log.info("微信支付V3通知签名信息: signature={}, timestamp={}, nonce={}, serial={}",
                wechatpaySignature, wechatpayTimestamp, wechatpayNonce, wechatpaySerial);

        try {
            // 验证必要的请求头
//            if (StrUtil.isBlank(wechatpaySignature) || StrUtil.isBlank(wechatpayTimestamp)
//                || StrUtil.isBlank(wechatpayNonce) || StrUtil.isBlank(wechatpaySerial)) {
//                log.error("微信支付V3通知缺少必要的签名头信息");
//                return WxPayNotifyResponse.fail("缺少必要的签名头信息");
//            }

            // 解析并验证通知 - 使用V3版本的解析方法
            // 注意：parseOrderNotifyResult方法在V3配置下会自动进行签名验证
            WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(notifyData);

            log.info("微信支付V3通知解析结果：商户订单号={}, 微信支付订单号={}, 支付状态={}",
                    notifyResult.getOutTradeNo(), notifyResult.getTransactionId(), notifyResult.getResultCode());

            // 处理不同的支付状态
            String resultCode = notifyResult.getResultCode();

            log.info("微信支付V3通知状态：resultCode={}", resultCode);

            if ("SUCCESS".equals(resultCode)) {
                // 支付成功，更新订单状态
                BizTicketOrderIdParam param = new BizTicketOrderIdParam();
                param.setId(notifyResult.getOutTradeNo());
                BizOrder order = bizTicketOrderService.detail(param);

                if (order == null) {
                    log.error("订单不存在：{}", notifyResult.getOutTradeNo());
                    return WxPayNotifyResponse.fail("订单不存在");
                }

                if ("待支付".equals(order.getStatus())) {
                    // 更新订单状态
                    bizTicketOrderService.lambdaUpdate()
                            .eq(BizOrder::getId, notifyResult.getOutTradeNo())
                            .set(BizOrder::getStatus, "已支付")
                            .set(BizOrder::getWxOrderId, notifyResult.getTransactionId()) // 更新为真正的微信支付交易号
                            .update();

                    // 重新获取更新后的订单
                    order = bizTicketOrderService.detail(param);
                    log.info("订单{}支付成功，已更新状态，微信支付交易号: {}", notifyResult.getOutTradeNo(), notifyResult.getTransactionId());

                    // 发送钉钉通知
                    sendOrderPaymentNotification(order, new Date());
                } else {
                    log.warn("订单{}状态不是待支付，当前状态：{}", notifyResult.getOutTradeNo(), order.getStatus());
                }
            } else {
                // 支付失败或其他状态
                log.warn("微信支付V3通知非成功状态：订单号={}, resultCode={}",
                        notifyResult.getOutTradeNo(), resultCode);
            }

            // 返回成功响应
            log.info("微信支付V3通知处理完成，订单号：{}", notifyResult.getOutTradeNo());
            return WxPayNotifyResponse.success("成功");

        } catch (WxPayException e) {
            log.error("处理微信支付V3通知失败，WxPayException: {}", e.getMessage(), e);
            // 对于签名验证失败等情况，返回失败响应
            return WxPayNotifyResponse.fail("签名验证失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("处理微信支付V3通知异常，Exception: {}", e.getMessage(), e);
            // 对于其他异常，也返回失败响应
            return WxPayNotifyResponse.fail("处理失败：" + e.getMessage());
        }
    }

    /**
     * 查询订单支付状态
     */
    @ApiOperationSupport(order = 3)
    @ApiOperation("查询订单支付状态")
    @GetMapping("/queryOrderStatus")
    public CommonResult<Map<String, Object>> queryOrderStatus(@RequestParam String orderId) {
        try {
            Map<String, Object> resultMap = new HashMap<>();

            // 从数据库查询订单状态
            BizTicketOrderIdParam param = new BizTicketOrderIdParam();
            param.setId(orderId);
            BizOrder order = bizTicketOrderService.detail(param);

            if (order == null) {
                throw new CommonException("订单不存在");
            }

            // 如果订单状态是待支付，则查询微信支付状态
            if ("待支付".equals(order.getStatus())) {
                try {
                    // 调用微信支付V3查询接口
                    WxPayOrderQueryV3Result wxOrderResult = wxPayService.queryOrderV3(null, orderId);

                    log.info("查询微信订单状态，订单号: {}, 交易状态: {}", orderId, wxOrderResult.getTradeState());

                    // 如果微信支付已成功，但数据库未更新，则更新订单状态
                    if ("SUCCESS".equals(wxOrderResult.getTradeState())) {
                        bizTicketOrderService.lambdaUpdate()
                            .eq(BizOrder::getId, orderId)
                            .set(BizOrder::getStatus, "已支付")
                            .set(BizOrder::getWxOrderId, wxOrderResult.getTransactionId()) // 保存真正的微信支付交易号
                            .update();
                        order.setStatus("已支付");
                        log.info("更新订单状态为已支付，订单号: {}, 微信支付交易号: {}", orderId, wxOrderResult.getTransactionId());

                        // 重新获取更新后的订单
                        order = bizTicketOrderService.detail(param);

                        // 发送钉钉通知
                        Date payTime = null;
                        if (wxOrderResult.getSuccessTime() != null) {
                            payTime = new Date(); // 如果有成功时间，使用该时间
                        }
                        sendOrderPaymentNotification(order, payTime);
                    }

                    // 添加微信返回的支付状态
                    resultMap.put("wxPayStatus", wxOrderResult.getTradeState());
                    resultMap.put("tradeStateDesc", wxOrderResult.getTradeStateDesc());
                } catch (Exception e) {
                    log.error("查询微信支付状态失败", e);
                    resultMap.put("wxPayError", e.getMessage());
                    // 查询失败不影响返回结果
                }
            }

            resultMap.put("orderId", orderId);
            resultMap.put("status", order.getStatus());
            resultMap.put("isPaid", "已支付".equals(order.getStatus()));

            return CommonResult.data(resultMap);
        } catch (Exception e) {
            log.error("查询订单状态失败", e);
            throw new CommonException("查询订单状态失败: " + e.getMessage());
        }
    }

    /**
     * 申请退款
     */
    @ApiOperationSupport(order = 4)
    @ApiOperation("申请退款")
    @PostMapping("/refund")
    @CommonLog("门票订单退款")
    public CommonResult<String> refund(@RequestBody BizTicketOrderIdParam bizTicketOrderIdParam) {
        try {
            // 查询订单信息
            BizOrder order = bizTicketOrderService.detail(bizTicketOrderIdParam);
            if (order == null) {
                throw new CommonException("订单不存在");
            }

            if (!"已支付".equals(order.getStatus())) {
                throw new CommonException("该订单状态不支持退款");
            }

            // 当前日期
            Date currentDate = new Date();
            // 如果预约时间存在且未过期
            if (order.getReservationTime() != null &&
                order.getReservationTime().after(currentDate)) {
                throw new CommonException("该订单已预约且未过期，不支持退款");
            }

            if (StrUtil.isBlank(order.getWxOrderId())) {
                throw new CommonException("订单缺少微信支付交易号，无法退款");
            }

            // 生成退款单号
            String refundId = "R" + System.currentTimeMillis() + order.getId().substring(0, 8);

            // 调用退款接口V3
            WxPayRefundV3Request request = new WxPayRefundV3Request();
            // 原订单号
            request.setOutTradeNo(order.getId());
            // 退款单号
            request.setOutRefundNo(refundId);

            // 订单金额
            WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
            // 订单总金额，单位为分
            int totalFee = order.getPrice().multiply(new BigDecimal("100")).intValue();
            amount.setTotal(totalFee);
            // 退款金额，单位为分
            amount.setRefund(totalFee);
            amount.setCurrency("CNY");
            request.setAmount(amount);

            log.info("申请退款，订单号: {}, 退款单号: {}, 退款金额: {}", order.getId(), refundId, totalFee);

            // V3退款结果直接返回
            wxPayService.refundV3(request);
            log.info("退款申请成功，订单号: {}, 退款单号: {}", order.getId(), refundId);

            // 更新订单状态为申请退款中
            bizTicketOrderService.lambdaUpdate()
                .eq(BizOrder::getId, order.getId())
                .set(BizOrder::getStatus, "申请退款中")
                .set(BizOrder::getWxRefundNo, refundId) // 保存退款单号，用于后续查询
                .update();
            // 恢复库存
            bizTicketOrderService.refund(bizTicketOrderIdParam);
            return CommonResult.ok("退款申请已提交，等待处理");
        } catch (Exception e) {
            log.error("退款申请失败", e);
            throw new CommonException("退款申请失败: " + e.getMessage());
        }
    }

    /**
     * 关闭订单
     */
    @ApiOperationSupport(order = 5)
    @ApiOperation("关闭订单")
    @PostMapping("/closeOrder")
    @CommonLog("关闭支付订单")
    public CommonResult<String> closeOrder(@RequestBody BizTicketOrderIdParam bizTicketOrderIdParam) {
        try {
            // 查询订单信息
            BizOrder order = bizTicketOrderService.detail(bizTicketOrderIdParam);
            if (order == null) {
                throw new CommonException("订单不存在");
            }

            if (!"待支付".equals(order.getStatus())) {
                throw new CommonException("只有待支付状态的订单可以关闭");
            }

            // 调用关闭订单接口V3
            wxPayService.closeOrderV3(order.getId());
            log.info("关闭微信支付订单成功，订单号: {}", order.getId());

            // 更新订单状态
            bizTicketOrderService.lambdaUpdate()
                .eq(BizOrder::getId, order.getId())
                .set(BizOrder::getStatus, "已关闭")
                .update();

            return CommonResult.ok("订单关闭成功");
        } catch (Exception e) {
            log.error("关闭订单失败", e);
            throw new CommonException("关闭订单失败: " + e.getMessage());
        }
    }

    /**
     * 获取请求体内容
     */
    private String getRequestBody(HttpServletRequest request) {
        try {
            StringBuilder sb = new StringBuilder();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = request.getInputStream().read(buffer)) != -1) {
                sb.append(new String(buffer, 0, length));
            }
            return sb.toString();
        } catch (Exception e) {
            throw new CommonException("获取请求体失败: " + e.getMessage());
        }
    }

    /**
     * 测试微信支付V3接口
     */
    @GetMapping("/testV3Api")
    @ApiOperation(value = "测试微信支付V3接口", notes = "专门用于测试微信支付V3接口连通性")
    public CommonResult<Map<String, Object>> testV3Api() {
        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 检查配置信息
            result.put("appId", wxPayService.getConfig().getAppId());
            result.put("mchId", wxPayService.getConfig().getMchId());
            result.put("apiV3Key", "******" + (wxPayService.getConfig().getApiV3Key() != null &&
                    wxPayService.getConfig().getApiV3Key().length() > 4 ?
                    wxPayService.getConfig().getApiV3Key().substring(
                        wxPayService.getConfig().getApiV3Key().length() - 4) : "****"));
            result.put("privateKeyPath", wxPayService.getConfig().getPrivateKeyPath());
            result.put("privateCertPath", wxPayService.getConfig().getPrivateCertPath());

            // 2. 检查证书配置
            try {
                result.put("certSerialNumber", wxPayService.getConfig().getCertSerialNo());
                result.put("hasCertificate", true);
            } catch (Exception e) {
                result.put("hasCertificate", false);
                result.put("certError", e.getMessage());
            }

            // 3. 尝试发送一个简单的查询请求
            String testOrderId = "TEST" + System.currentTimeMillis();
            try {
                wxPayService.queryOrderV3(null, testOrderId);
            } catch (WxPayException e) {
                // 预期会失败，但我们关注的是失败原因
                result.put("queryTestOrderIdResult", e.getReturnMsg());

                // 如果能正确访问API但返回订单不存在，说明配置正确
                if (e.getMessage() != null && e.getMessage().contains("订单不存在")) {
                    result.put("v3ApiAccessible", true);
                    result.put("message", "API V3接口访问正常");
                } else {
                    result.put("v3ApiAccessible", false);
                    result.put("message", "API V3接口访问异常: " + e.getMessage());
                }
            }

            return CommonResult.data(result);
        } catch (Exception e) {
            result.put("error", e.getMessage());
            return CommonResult.data(result);
        }
    }

    /**
     * 获取小程序支付参数
     */
    @ApiOperationSupport(order = 6)
    @ApiOperation("获取小程序支付参数")
    @GetMapping("/getPayParams")
    public CommonResult<Map<String, String>> getPayParams(@RequestParam String prepayId) {
        try {
            if (StrUtil.isBlank(prepayId)) {
                throw new CommonException("预支付ID不能为空");
            }

            // 生成小程序调起支付的参数
            log.info("开始重新生成微信支付参数，appId: {}, prepayId: {}",
                wxPayService.getConfig().getAppId(),
                prepayId);

            // 确保私钥内容已加载
            if (StrUtil.isBlank(privateKeyContent)) {
                loadPrivateKeyContent();
            }

            Map<String, String> payInfo = WxPaySignUtil.createPaySignatureWithPrivateKey(
                wxPayService.getConfig().getAppId(),
                prepayId,
                privateKeyContent
            );
            log.info("重新生成小程序支付参数成功，prepayId: {}, 参数: {}", prepayId, payInfo);

            return CommonResult.data(payInfo);
        } catch (Exception e) {
            log.error("获取小程序支付参数失败", e);
            throw new CommonException("获取小程序支付参数失败: " + e.getMessage());
        }
    }

    /** 手动触发分账判断 */
    @ApiOperationSupport(order = 7)
    @GetMapping("/getStartFz")
    public void getStartFz() {
        myWxPayService.updateOrderStatusToCompleted();
    }



    /**
     * 定时任务： 每分钟执行，处理待支付订单状态更新为已支付
     */
    @Scheduled(cron = "5 0/5 * * * ?")
    public void updateOrderStatusToPaid() {
        // 查询所有符合条件的未支付订单
        LambdaQueryWrapper<BizOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizOrder::getStatus, "未支付");
        List<BizOrder> unPaidOrders = bizTicketOrderService.list(queryWrapper);

        for (BizOrder order : unPaidOrders) {
            try {
                String orderId = order.getId();
                // 调用微信支付V3查询接口
                WxPayOrderQueryV3Result wxOrderResult = wxPayService.queryOrderV3(null, orderId);

                log.info("查询微信订单状态，订单号: {}, 交易状态: {}", orderId, wxOrderResult.getTradeState());

                // 如果微信支付已成功，但数据库未更新，则更新订单状态
                if ("SUCCESS".equals(wxOrderResult.getTradeState())) {
                    // 再次查询订单状态，判断是否是未支付
                    BizTicketOrderIdParam param = new BizTicketOrderIdParam();
                    param.setId(orderId);
                    order = bizTicketOrderService.detail(param);
                    order.setWxOrderId(wxOrderResult.getTransactionId());
                    bizTicketOrderService.updateById(order);
                    if ("未支付".equals(order.getStatus())) {
                        bizTicketOrderService.lambdaUpdate()
                                .eq(BizOrder::getId, orderId)
                                .set(BizOrder::getStatus, "已支付")
//                                .set(BizOrder::getWxOrderId, wxOrderResult.getTransactionId()) // 保存真正的微信支付交易号
                                .update();
//                        order.setStatus("已支付");
                        log.info("更新订单状态为已支付，订单号: {}, 微信支付交易号: {}", orderId, wxOrderResult.getTransactionId());

                        // 重新获取更新后的订单

                        order = bizTicketOrderService.detail(param);

                        // 发送钉钉通知
                        Date payTime = null;
                        if (wxOrderResult.getSuccessTime() != null) {
                            payTime = new Date(); // 如果有成功时间，使用该时间
                        }
                        sendOrderPaymentNotification(order, payTime);
                    }
                }
            } catch (Exception e) {
                log.error("查询微信支付状态失败", e);
            }
        }

    }
}
